//package cn.lysoy.demo.aspect;
//
//import cn.lysoy.demo.entity.MapperLog;
//import cn.lysoy.demo.service.MapperLogService;
//import com.alibaba.fastjson.JSON;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.ibatis.annotations.Param;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.mapping.ParameterMapping;
//import org.apache.ibatis.reflection.MetaObject;
//import org.apache.ibatis.session.Configuration;
//import org.apache.ibatis.session.SqlSessionFactory;
//import org.apache.ibatis.type.TypeHandlerRegistry;
//import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.Signature;
//import org.aspectj.lang.annotation.*;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.Resource;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.lang.annotation.Annotation;
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.net.InetAddress;
//import java.net.UnknownHostException;
//import java.text.DateFormat;
//import java.util.*;
//
//@Component
//@Aspect
//@Slf4j
//public class MapperAspect {
//    @Resource
//    @Qualifier("mapperLogService")
//    private MapperLogService service;
//
//    @Resource
//    private SqlSessionFactory sqlSessionFactory;
//
//    private String className; // request类名
//    private String methodName;      // 方法名
//    private String sql; // 传入sql
//    private String requestBody; // 传入参数
//    private long startTimeMillis = 0; // 开始时间
//    private long endTimeMillis = 0; // 结束时间
//    private Date requestDate = null;
//
//    @Pointcut("execution( public * cn.lysoy.demo.mapper.*.*(..))")
//    public void aopPointCut() {
//    }
//
//    /**
//     * @Description: 获取请求参数
//     **/
//    public String getRequestParam(JoinPoint joinPoint) {
//        Signature signature = joinPoint.getSignature();
//        // 参数名数组
//        String[] parameterNames = ((MethodSignature) signature).getParameterNames();
//        // 构造参数组集合
//        if (null == parameterNames || parameterNames.length == 0) {
//            return "";
//        }
//        HashMap<Object,Object> inputParamMap = new HashMap<>();
//        Object[] args = joinPoint.getArgs();
//        for (int i = 0; i < args.length; i++) {
//            //request/response无法使用toJSON
//            if (args[i] instanceof HttpServletRequest) {
//                inputParamMap.put(JSON.toJSON(parameterNames[i]), "request");
//            } else if (args[i] instanceof HttpServletResponse) {
//                inputParamMap.put(JSON.toJSON(parameterNames[i]), "response");
//            } else {
//                inputParamMap.put(JSON.toJSON(parameterNames[i]), JSON.toJSON(args[i]));
//            }
//        }
//        return JSON.toJSON(inputParamMap).toString();
//    }
//
//    @Before("aopPointCut()")
//    public void doBefore(JoinPoint joinPoint) {
//        this.className = joinPoint.getTarget().getClass().getName();
//        this.methodName = joinPoint.getSignature().getName();
//        this.requestBody = getRequestParam(joinPoint);
//        this.startTimeMillis = System.currentTimeMillis();
//        this.requestDate = new Date();
//    }
//
//    /**
//     * @Description: 方法调用后触发   记录
//     */
//    @AfterReturning(value = "aopPointCut()", returning = "returnValue")
//    public void after(JoinPoint joinPoint, Object returnValue) {
//        Object[] arguments = joinPoint.getArgs();
//        Class targetClass = null;
//        try {
//            targetClass = Class.forName(this.className);
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
//        Method[] methods = targetClass.getMethods();
//        for (Method method : methods) {
//            if (method.getName().equals(this.methodName)) {
//                Class[] clazzs = method.getParameterTypes();
//                if (clazzs != null && clazzs.length == arguments.length ) {
//                    String message = null;
//                    if (returnValue == null){message="";}else{ message = returnValue.toString();
//                        if (message.length() > 1000) {
//                            message = message.substring(0, 1000);
//                        }}
//                    this.endTimeMillis = System.currentTimeMillis();
//                    String ip;
//                    try {
//                        //获取IP地址
//                        ip = InetAddress.getLocalHost().getHostAddress();
//                        MapperLog requestLog = new MapperLog();
//                        requestLog.setClassName(this.className);
//                        requestLog.setMethodName(this.methodName);
//                        requestLog.setRequestIp(ip);
//                        requestLog.setReturnValue(message);
//                        requestLog.setRequestBody(this.requestBody);
//                        requestLog.setRequestSql(this.sql);
//                        requestLog.setRequestDate(this.requestDate);
//                        requestLog.setHandleTime(this.endTimeMillis-this.startTimeMillis);
//                        try {
//                            service.save(requestLog);
//                        }catch (Exception e) {
//                            log.info(e.getMessage());
//                        }
//
//                    } catch (UnknownHostException e) {
//                        e.printStackTrace();
//                    }
//                }}}}
//
//
//    @Around("aopPointCut()")
//    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable{
//        try {
//            this.sql = getMybatisSql(joinPoint, sqlSessionFactory);
//        }catch (Exception e) {
//
//        }
//
//        long start = System.currentTimeMillis();
//        try {
//            Object result = joinPoint.proceed();
//            long end = System.currentTimeMillis();
//            log.info("======Controller around " + joinPoint + "\t 耗时为：: " + (end - start) + " ms!");
//            return result;
//        } catch (Throwable e) {
//            long end = System.currentTimeMillis();
//            log.info("======Controller around " + joinPoint + "\t 耗时为：: " + (end - start) + " ms with exception : " + e.getMessage());
//            throw e;
//        }
//    }
//
//    /**
//     * 获取aop中的SQL语句
//     *
//     * @param pjp
//     * @param sqlSessionFactory
//     * @return
//     * @throws IllegalAccessException
//     */
//    public static String getMybatisSql(ProceedingJoinPoint pjp, SqlSessionFactory sqlSessionFactory) throws IllegalAccessException {
//        Map<String, Object> map = new HashMap<>(16);
//        //1.获取namespace+methdoName
//        MethodSignature signature = (MethodSignature) pjp.getSignature();
//        Method method = signature.getMethod();
//        String namespace = method.getDeclaringClass().getName();
//        String methodName = method.getName();
//        //2.根据namespace+methdoName获取相对应的MappedStatement
//        Configuration configuration = sqlSessionFactory.getConfiguration();
//        MappedStatement mappedStatement = configuration.getMappedStatement(namespace + "." + methodName);
////        //3.获取方法参数列表名
////        Parameter[] parameters = method.getParameters();
//        //4.形参和实参的映射
//        Object[] objects = pjp.getArgs(); //获取实参
//        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
//        for (int i = 0; i < parameterAnnotations.length; i++) {
//            Object object = objects[i];
//            if (parameterAnnotations[i].length == 0) { //说明该参数没有注解，此时该参数可能是实体类，也可能是Map，也可能只是单参数
//                if (object.getClass().getClassLoader() == null && object instanceof Map) {
//                    map.putAll((Map<? extends String, ?>) object);
//                    System.out.println("该对象为Map");
//                } else {//形参为自定义实体类
//                    map.putAll(objectToMap(object));
//                    System.out.println("该对象为用户自定义的对象");
//                }
//            } else {//说明该参数有注解，且必须为@Param
//                for (Annotation annotation : parameterAnnotations[i]) {
//                    if (annotation instanceof Param) {
//                        map.put(((Param) annotation).value(), object);
//                    }
//                }
//            }
//        }
//        //5.获取boundSql
//        BoundSql boundSql = mappedStatement.getBoundSql(map);
//        return showSql(configuration, boundSql);
//    }
//
//    /**
//     * 解析BoundSql，生成不含占位符的SQL语句
//     *
//     * @param configuration
//     * @param boundSql
//     * @return
//     */
//    private static String showSql(Configuration configuration, BoundSql boundSql) {
//        Object parameterObject = boundSql.getParameterObject();
//        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
//        String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
//        if (parameterMappings.size() > 0 && parameterObject != null) {
//            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
//            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
//                sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
//            } else {
//                MetaObject metaObject = configuration.newMetaObject(parameterObject);
//                for (ParameterMapping parameterMapping : parameterMappings) {
//                    String propertyName = parameterMapping.getProperty();
//                    String[] s = metaObject.getObjectWrapper().getGetterNames();
//                    s.toString();
//                    if (metaObject.hasGetter(propertyName)) {
//                        Object obj = metaObject.getValue(propertyName);
//                        sql = sql.replaceFirst("\\?", getParameterValue(obj));
//                    } else if (boundSql.hasAdditionalParameter(propertyName)) {
//                        Object obj = boundSql.getAdditionalParameter(propertyName);
//                        sql = sql.replaceFirst("\\?", getParameterValue(obj));
//                    }
//                }
//            }
//        }
//        return sql;
//    }
//
//    /**
//     * 若为字符串或者日期类型，则在参数两边添加''
//     *
//     * @param obj
//     * @return
//     */
//    private static String getParameterValue(Object obj) {
//        String value;
//        if (obj instanceof String) {
//            value = "'" + obj + "'";
//        } else if (obj instanceof Date) {
//            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
//            value = "'" + formatter.format(new Date()) + "'";
//        } else {
//            if (obj != null) {
//                value = obj.toString();
//            } else {
//                value = "";
//            }
//        }
//        return value;
//    }
//
//    /**
//     * 获取利用反射获取类里面的值和名称
//     *
//     * @param obj
//     * @return
//     * @throws IllegalAccessException
//     */
//    private static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
//        Map<String, Object> map = new HashMap<>();
//        Class<?> clazz = obj.getClass();
//        System.out.println(clazz);
//        for (Field field : clazz.getDeclaredFields()) {
//            field.setAccessible(true);
//            String fieldName = field.getName();
//            Object value = field.get(obj);
//            map.put(fieldName, value);
//        }
//        return map;
//    }
//}
